import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';
import { LLMFactory } from '../../../core/llm/llmFactory';
import { Logger } from '../../../src/logger/Logger';
import { BaseLLM } from '../../../core/llm/baseLLM';
import { ModelSelector } from '../../../core/llm/modelSelector';
import { ProjectAnalyzer } from '../UnitTest/ProjectAnalyzer';
import { GNFileManager } from '../UnitTest/GNFileManager';

// 导入新的服务类
import { FuzzProjectAnalyzer } from './services/FuzzProjectAnalyzer';
import { FuzzFileGenerator } from './services/FuzzFileGenerator';
import { FuzzBuildGNUpdater } from './services/FuzzBuildGNUpdater';
import { FuzzStructureCreator } from './utils/FuzzStructureCreator';
import { FuzzNameUtils } from './utils/FuzzNameUtils';
import { FuzzerContext, SourceGNConfig } from './types/FuzzTypes';

/**
 * OpenHarmony Fuzz 测试生成器（重构版）
 * 采用模块化设计，将功能拆分到多个服务类中
 */
export class FuzzTestGenerator {
    private llmFactory: LLMFactory;
    private sendMessage: (msg: any) => void;
    private currentAbortController: AbortController | null = null;
    private isPaused: boolean = false;
    private pausePromiseResolver: (() => void) | null = null;
    private fileGenerator: FuzzFileGenerator;

    constructor(llmFactory: LLMFactory, sendMessage: (msg: any) => void) {
        this.llmFactory = llmFactory;
        this.sendMessage = sendMessage;
        this.fileGenerator = new FuzzFileGenerator(sendMessage);
    }

    /**
     * 暂停当前操作
     */
    public pauseCurrentOperation(): void {
        if (this.currentAbortController && !this.isPaused) {
            this.isPaused = true;
            Logger.info('[FuzzTestGenerator] ⏸️  用户暂停操作');
        this.sendMessage({
            type: 'info',
                content: '⏸️  已暂停 - 您可以查看当前内容，选择【▶️ 继续】或【❌ 取消】'
            });
        }
    }

    /**
     * 继续当前操作
     */
    public resumeCurrentOperation(): void {
        if (this.isPaused) {
            this.isPaused = false;
            if (this.pausePromiseResolver) {
                this.pausePromiseResolver();
                this.pausePromiseResolver = null;
            }
            Logger.info('[FuzzTestGenerator] ▶️  用户继续操作');
        this.sendMessage({
            type: 'info',
                content: '▶️  已继续 - 生成将从暂停处继续...'
            });
        }
    }

    /**
     * 取消当前操作
     */
    public cancelCurrentOperation(): void {
        if (this.currentAbortController) {
            this.currentAbortController.abort();
            this.currentAbortController = null;
            this.isPaused = false;
            this.pausePromiseResolver = null;
            Logger.info('[FuzzTestGenerator] ❌ 用户取消操作');
            this.sendMessage({
                type: 'warning',
                content: '❌ 已取消 - 生成操作已终止',
                level: 'warning'
            });
        }
    }

    /**
     * 获取当前状态
     */
    public getCurrentState(): { isRunning: boolean; isPaused: boolean } {
        return {
            isRunning: this.currentAbortController !== null,
            isPaused: this.isPaused
        };
    }

    /**
     * 执行完整的 Fuzz 测试生成流程
     */
    public async executeFullWorkflow(
        document: vscode.TextDocument,
        sourceCode: string,
        isWholeFile: boolean = false
    ): Promise<void> {
        try {
            // === 步骤1：定位项目根目录 ===
            const sourceDir = path.dirname(document.uri.fsPath);
            const projectRoot = GNFileManager.findProjectRoot(document.uri.fsPath) || sourceDir;

            this.sendMessage({
                type: 'info',
                content: `📁 **项目信息**\n\n` +
                        `- 源文件目录：\`${sourceDir}\`\n` +
                        `- 项目根目录：\`${projectRoot}\``
            });

            // === 如果是整个文件，提取所有函数并为每个生成 fuzzer ===
            if (isWholeFile) {
                await this.generateFuzzersForAllFunctions(document, sourceCode, projectRoot);
                return;
            }

            // === 步骤2：使用 ProjectAnalyzer 查找和解析 BUILD.gn ===
                    this.sendMessage({
                type: 'info',
                content: `🔍 **第二步：查找源文件的 BUILD.gn 配置**\n\n正在分析...`
            });
            
            const projectAnalyzer = new ProjectAnalyzer();
            const sourceFileInfo = await projectAnalyzer.analyzeSourceFile(document.uri.fsPath);
            
            const buildGnPath = sourceFileInfo.sourceBuildGN?.filePath || null;

            if (buildGnPath) {
            this.sendMessage({
                    type: 'info',
                    content: `✅ **找到 BUILD.gn 文件！**\n\n` +
                            `- 文件路径：\`${buildGnPath}\`\n` +
                            `- 包含 ${sourceFileInfo.sourceBuildGN?.targets.length || 0} 个编译目标`,
                    filePath: buildGnPath
                });
            } else {
            this.sendMessage({
                    type: 'warning',
                    content: `⚠️ 未找到包含当前源文件的 BUILD.gn 配置\n\n将使用基本配置生成 Fuzz 测试。`
                });
            }

            // === 步骤3：生成 Fuzzer 名称和目录结构 ===
            const fuzzerName = FuzzNameUtils.generateFuzzerName(document.uri.fsPath);
            const structure = FuzzStructureCreator.createFuzzerStructure(document.uri.fsPath, fuzzerName);
                            
                            this.sendMessage({
                                type: 'info',
                content: `✅ **目录结构已创建！**\n\n` +
                        `📂 **项目根目录**：\`${structure.projectRoot}\`\n\n` +
                        `📂 **Fuzzer 目录**：\`${structure.fuzzerDir}\`\n\n` +
                        `\`\`\`\n${FuzzStructureCreator.visualizeStructure(fuzzerName)}\n\`\`\``,
                filePath: structure.fuzzerDir
            });

            // === 步骤4：提取 GN 配置 ===
            let sourceGNConfig: SourceGNConfig | null = null;
            let buildGnContent = '';
            
            if (sourceFileInfo && sourceFileInfo.sourceBuildGN && sourceFileInfo.sourceBuildGN.targets.length > 0) {
                const matchedTarget = this.findMatchedTarget(
                    sourceFileInfo.sourceBuildGN.targets,
                    document.uri.fsPath
                );
                
                if (matchedTarget) {
                    sourceGNConfig = {
                        deps: matchedTarget.deps || [],
                        include_dirs: matchedTarget.include_dirs || [],
                        external_deps: matchedTarget.external_deps || [],
                        configs: matchedTarget.configs || [],
                        defines: matchedTarget.defines || []
                    };
                    
                    Logger.info(`[FuzzTestGenerator] ✅ 成功提取源文件 GN 配置 (target: ${matchedTarget.name})`);
                }
            } else if (buildGnPath && fs.existsSync(buildGnPath)) {
                buildGnContent = fs.readFileSync(buildGnPath, 'utf-8');
            }

            // === 步骤5：提取项目信息 ===
            const projectInfo = FuzzProjectAnalyzer.extractProjectInfo(
                document.uri.fsPath,
                buildGnContent,
                sourceFileInfo
            );

            // === 步骤6：构建上下文并生成代码 ===
            const context: FuzzerContext = {
                sourceFile: document.uri.fsPath,
                sourceCode,
                fuzzerDir: structure.fuzzerDir,
                fuzzerName,
                projectRoot: structure.projectRoot,
                projectInfo,
                sourceGNConfig,
                buildGnContent
            };

            await this.generateFuzzFiles(context);

            // === 步骤7：更新父级 BUILD.gn ===
            await this.updateParentBuildGN(structure, fuzzerName);

            } catch (error: any) {
            this.sendMessage({
                type: 'error',
                content: `❌ 生成过程中出错：${error.message}`
            });
            throw error;
        }
    }

    /**
     * 生成 Fuzz 测试文件
     */
    private async generateFuzzFiles(context: FuzzerContext): Promise<void> {
        this.sendMessage({
            type: 'info',
            content: '🚀 **开始逐个生成 Fuzz 测试文件...**\n\n' +
                    '将依次生成 5 个文件，每个文件都会实时显示生成过程'
        });

        // 获取 LLM 实例
        const selectedModel = ModelSelector.selectModel('fuzzTest');
        let llm = this.llmFactory.getLLM(selectedModel);
        
        if (!llm) {
            const fallbackModels = ModelSelector.getFallbackModels('fuzzTest');
            for (const fallbackModel of fallbackModels) {
                llm = this.llmFactory.getLLM(fallbackModel);
                if (llm) break;
                }
            if (!llm) {
                throw new Error('无法获取 LLM 实例');
            }
        }

        // 创建 AbortController
        this.currentAbortController = new AbortController();

        // 同步控制状态到 FileGenerator
        this.fileGenerator.setControlState(
            this.currentAbortController,
            this.isPaused,
            this.pausePromiseResolver
        );

        // 生成所有文件
        await this.fileGenerator.generateAllFiles(llm, context);

        // 清理
        this.currentAbortController = null;
    }

    /**
     * 更新父级 BUILD.gn
     */
    private async updateParentBuildGN(
        structure: { fuzzTestDir: string; fuzzerDir: string },
        fuzzerName: string
    ): Promise<void> {
        this.sendMessage({
            type: 'info',
            content: `📝 **第六步：更新父级 BUILD.gn**\n\n正在注册 Fuzzer...`
        });

        // 确保父级 BUILD.gn 存在
        FuzzBuildGNUpdater.createParentBuildGNIfNotExists(structure.fuzzTestDir);

        // 读取生成的 BUILD.gn 以提取 test target 名称
        const fuzzerBuildGnPath = path.join(structure.fuzzerDir, 'BUILD.gn');
        let testTargetName = FuzzNameUtils.toCamelCase(fuzzerName) + 'FuzzTest';
        
        if (fs.existsSync(fuzzerBuildGnPath)) {
            const gnContent = fs.readFileSync(fuzzerBuildGnPath, 'utf-8');
            const extracted = FuzzBuildGNUpdater.extractTestTargetName(gnContent);
            if (extracted) {
                testTargetName = extracted;
            }
        }

        const fuzzerDirName = path.basename(structure.fuzzerDir);
        const success = FuzzBuildGNUpdater.updateParentBuildGN(
            structure.fuzzTestDir,
            fuzzerDirName,
            testTargetName
        );

        if (success) {
            this.sendMessage({
                type: 'success',
                content: `✅ **已更新父级 BUILD.gn**\n\n` +
                        `添加依赖：\`./${fuzzerDirName}:${testTargetName}\``
            });
        } else {
            this.sendMessage({
                type: 'warning',
                content: `⚠️ **未能自动更新父级 BUILD.gn**\n\n` +
                        `请手动添加：\`./${fuzzerDirName}:${testTargetName}\``
            });
        }
    }

    /**
     * 查找匹配的 GN target
     */
    private findMatchedTarget(targets: any[], sourceFile: string): any | null {
        const sourceFileName = path.basename(sourceFile);
        const normalizedFilePath = path.normalize(sourceFile).toLowerCase().replace(/\\/g, '/');
        
        for (const target of targets) {
            for (const source of target.sources) {
                const normalizedSource = path.normalize(source).toLowerCase().replace(/\\/g, '/');
                if (normalizedSource === normalizedFilePath || path.basename(source) === sourceFileName) {
                    return target;
                }
            }
        }
        
        return null;
    }

    /**
     * 为整个文件的所有函数生成 Fuzz 测试
     */
    private async generateFuzzersForAllFunctions(
        document: vscode.TextDocument,
        sourceCode: string,
        projectRoot: string
    ): Promise<void> {
        this.sendMessage({
            type: 'info',
            content: `🔍 **正在提取文件中的所有函数...**\n\n文件：\`${path.basename(document.uri.fsPath)}\``
        });

        // 提取所有可测试函数
        const functions = await this.extractPublicFunctions(document, sourceCode);

        if (functions.length === 0) {
            this.sendMessage({
                type: 'warning',
                content: `⚠️ **未找到可测试的函数**\n\n将为整个文件生成一个 fuzzer。`
            });
            // 🔧 修复：回退到生成单个 fuzzer（为整个文件生成）
            Logger.info(`[FuzzTestGenerator] ⚠️ 未提取到函数，回退到整个文件模式`);
            
            // 调用原始的单文件生成流程
            try {
                // 使用 ProjectAnalyzer 查找 BUILD.gn
                const projectAnalyzer = new ProjectAnalyzer();
                const sourceFileInfo = await projectAnalyzer.analyzeSourceFile(document.uri.fsPath);
                const buildGnPath = sourceFileInfo.sourceBuildGN?.filePath || null;
                
                // 生成 Fuzzer 名称和目录
                const fuzzerName = FuzzNameUtils.generateFuzzerName(document.uri.fsPath);
                const structure = FuzzStructureCreator.createFuzzerStructure(document.uri.fsPath, fuzzerName);
                
                // 提取 GN 配置
                let sourceGNConfig = null;
                let buildGnContent = '';
                if (buildGnPath) {
                    buildGnContent = fs.readFileSync(buildGnPath, 'utf-8');
                    sourceGNConfig = GNFileManager.extractSourceGNConfig(buildGnPath, document.uri.fsPath);
                }
                
                // 生成上下文
                const context: FuzzerContext = {
                    sourceFile: document.uri.fsPath,
                    sourceCode: sourceCode,  // 使用完整源代码
                    fuzzerDir: structure.fuzzerDir,
                    fuzzerName,
                    projectRoot: structure.projectRoot,
                    projectInfo: FuzzProjectAnalyzer.extractProjectInfo(document.uri.fsPath, buildGnContent, sourceFileInfo),
                    sourceGNConfig,
                    buildGnContent
                };
                
                // 生成文件
                await this.generateFuzzFiles(context);
                await this.updateParentBuildGN(structure, fuzzerName);
                
                this.sendMessage({
                    type: 'success',
                    content: `✅ **已为整个文件生成 Fuzzer！**`
                });
            } catch (error: any) {
                Logger.error(`[FuzzTestGenerator] ❌ 整个文件生成失败: ${error.message}`);
                this.sendMessage({
                    type: 'error',
                    content: `❌ **生成失败**\n\n${error.message}`
                });
            }
            return;
        }

        this.sendMessage({
            type: 'info',
            content: `✅ **找到 ${functions.length} 个函数**\n\n` +
                    functions.map((f, i) => `   ${i + 1}. ${f.name}`).join('\n') +
                    `\n\n将为每个函数生成独立的 fuzzer...`
        });

        // === 🔧 修复：在批量生成前，先查找源文件的 BUILD.gn 配置 ===
        Logger.info(`[FuzzTestGenerator] 📋 查找源文件的 BUILD.gn 配置...`);
        const projectAnalyzer = new ProjectAnalyzer();
        const sourceFileInfo = await projectAnalyzer.analyzeSourceFile(document.uri.fsPath);
        const buildGnPath = sourceFileInfo.sourceBuildGN?.filePath || null;
        
        let sourceGNConfig = null;
        let buildGnContent = '';
        
        if (buildGnPath) {
            buildGnContent = fs.readFileSync(buildGnPath, 'utf-8');
            sourceGNConfig = GNFileManager.extractSourceGNConfig(buildGnPath, document.uri.fsPath);
            if (sourceGNConfig) {
                Logger.info(`[FuzzTestGenerator] ✅ 找到源文件 BUILD.gn: ${buildGnPath}`);
                Logger.info(`[FuzzTestGenerator]    deps: ${sourceGNConfig.deps.length} 项`);
                Logger.info(`[FuzzTestGenerator]    external_deps: ${sourceGNConfig.external_deps.length} 项`);
                Logger.info(`[FuzzTestGenerator]    include_dirs: ${sourceGNConfig.include_dirs.length} 项`);
            } else {
                Logger.warn(`[FuzzTestGenerator] ⚠️ 找到 BUILD.gn 但无法提取配置: ${buildGnPath}`);
            }
        } else {
            Logger.warn(`[FuzzTestGenerator] ⚠️ 未找到源文件的 BUILD.gn`);
        }

        // 为每个函数生成 fuzzer
        let successCount = 0;
        for (let i = 0; i < functions.length; i++) {
            const func = functions[i];
            try {
                this.sendMessage({
                    type: 'info',
                    content: `🎯 [${i + 1}/${functions.length}] 正在为函数 ${func.name} 生成 Fuzz 测试...`
                });

                // 为单个函数生成 fuzzer
                const fuzzerName = FuzzNameUtils.generateFuzzerNameForFunction(func.name);
                const structure = FuzzStructureCreator.createFuzzerStructure(document.uri.fsPath, fuzzerName);

                // 🔧 修复：传递整个文件的源代码，让推理引擎能提取完整的依赖信息
                // 之前只传递函数签名会导致无法推断deps和external_deps
                const context: FuzzerContext = {
                    sourceFile: document.uri.fsPath,
                    sourceCode: sourceCode, // ✅ 传递完整源代码而不是单个函数签名，以便推断依赖
                    fuzzerDir: structure.fuzzerDir,
                    fuzzerName,
                    projectRoot: structure.projectRoot,
                    projectInfo: FuzzProjectAnalyzer.extractProjectInfo(document.uri.fsPath, buildGnContent, sourceFileInfo),
                    sourceGNConfig,      // ✅ 使用源文件的 GN 配置
                    buildGnContent       // ✅ 使用源文件的 GN 内容
                };

                await this.generateFuzzFiles(context);
                await this.updateParentBuildGN(structure, fuzzerName);

                successCount++;
                this.sendMessage({
                    type: 'success',
                    content: `✅ [${i + 1}/${functions.length}] 函数 ${func.name} 的 Fuzzer 生成完成！`
                });
            } catch (error: any) {
                this.sendMessage({
                    type: 'warning',
                    content: `⚠️ [${i + 1}/${functions.length}] 函数 ${func.name} 生成失败：${error.message}`
                });
            }
        }

        this.sendMessage({
            type: 'success',
            content: `🎉 **批量生成完成！**\n\n成功：${successCount}/${functions.length}`
        });
    }

    /**
     * 提取 C++ 文件中的可测试函数
     * 包括：
     * 1. 成员函数（从类定义中提取）
     * 2. 全局函数
     * 3. NDK 接口（OH_ 开头的函数）
     */
    private async extractPublicFunctions(
        document: vscode.TextDocument,
        sourceCode: string
    ): Promise<Array<{ name: string; signature: string }>> {
        const functions: Array<{ name: string; signature: string }> = [];
        const functionNames = new Set<string>();

        // === 策略1：提取 OH_ 开头的 NDK 接口（优先级最高）===
        const ndkRegex = /(?:^|\n)\s*(?:extern\s+(?:"C"\s+)?)?(\w+(?:\s*\*)?)\s+(OH_\w+)\s*\(([^)]*)\)\s*[{;]/g;
        let match;
        while ((match = ndkRegex.exec(sourceCode)) !== null) {
            const returnType = match[1].trim();
            const functionName = match[2].trim();
            const params = match[3].trim();

            if (!functionNames.has(functionName)) {
                functions.push({
                    name: functionName,
                    signature: `${returnType} ${functionName}(${params})`
                });
                functionNames.add(functionName);
                Logger.info(`[FuzzTestGenerator] ✅ 提取到 NDK 接口: ${functionName}`);
            }
        }

        // === 策略2：提取类的 public 成员函数 ===
        const publicSectionRegex = /public:\s*([\s\S]*?)(?:private:|protected:|^\s*\};?$)/gm;
        const publicMatches = [...sourceCode.matchAll(publicSectionRegex)];

        for (const publicMatch of publicMatches) {
            const publicSection = publicMatch[1];
            
            // 匹配成员函数
            const memberFuncRegex = /(?:virtual\s+)?(?:static\s+)?(?:inline\s+)?(\w+(?:<[\w\s,:<>*&]+>)?(?:\s*\*|\s*&)?)\s+(\w+)\s*\(([^)]*)\)(?:\s+const)?(?:\s+override)?(?:\s*=\s*0)?[{;]/g;
            
            let memberMatch;
            while ((memberMatch = memberFuncRegex.exec(publicSection)) !== null) {
                const returnType = memberMatch[1].trim();
                const functionName = memberMatch[2].trim();
                const params = memberMatch[3].trim();

                // 跳过构造函数、析构函数、operator
                if (functionName.startsWith('~') || 
                    functionName.startsWith('operator') ||
                    returnType === functionName) {
                    continue;
                }

                if (!functionNames.has(functionName)) {
                    functions.push({
                        name: functionName,
                        signature: `${returnType} ${functionName}(${params})`
                    });
                    functionNames.add(functionName);
                }
            }
        }

        // === 策略3：提取全局函数（非类成员）===
        // 匹配不在 class/struct 定义内的函数
        const globalFuncRegex = /(?:^|\n)(?:extern\s+(?:"C"\s+)?)?(?:static\s+)?(?:inline\s+)?(\w+(?:<[\w\s,:<>*&]+>)?(?:\s*\*|\s*&)?)\s+(\w+)\s*\(([^)]*)\)\s*\{/g;
        
        while ((match = globalFuncRegex.exec(sourceCode)) !== null) {
            const returnType = match[1].trim();
            const functionName = match[2].trim();
            const params = match[3].trim();

            // 跳过 main 函数
            if (functionName === 'main') {
                continue;
            }

            // 跳过已经提取过的函数
            if (functionNames.has(functionName)) {
                continue;
            }

            functions.push({
                name: functionName,
                signature: `${returnType} ${functionName}(${params})`
            });
            functionNames.add(functionName);
        }
        
        // === 策略4（新增）：提取类成员函数实现（.cpp 文件中的 ClassName::FunctionName）===
        // 匹配 返回类型 类名::函数名(参数) { 的模式
        const memberFuncImplRegex = /(\w+(?:<[\w\s,:<>*&]+>)?(?:\s*\*|\s*&)?)\s+(\w+)::(\w+)\s*\(([^)]*)\)(?:\s+const)?\s*\{/g;
        
        while ((match = memberFuncImplRegex.exec(sourceCode)) !== null) {
            const returnType = match[1].trim();
            const className = match[2].trim();
            const functionName = match[3].trim();
            const params = match[4].trim();
            
            // 跳过构造函数和析构函数
            if (functionName === className || functionName.startsWith('~')) {
                continue;
            }
            
            // 跳过 operator 重载
            if (functionName.startsWith('operator')) {
                continue;
            }
            
            // 使用完整名称（类名::函数名）作为唯一标识
            const fullName = `${className}::${functionName}`;
            
            if (!functionNames.has(fullName) && !functionNames.has(functionName)) {
                functions.push({
                    name: functionName,  // 只使用函数名，方便 fuzzer 命名
                    signature: `${returnType} ${className}::${functionName}(${params})`
                });
                functionNames.add(fullName);
                functionNames.add(functionName);
            }
        }

        if (functions.length > 0) {
            Logger.info(`[FuzzTestGenerator] ✅ 总计提取到 ${functions.length} 个可测试函数`);
            Logger.info(`[FuzzTestGenerator]    - NDK 接口 (OH_*): ${functions.filter(f => f.name.startsWith('OH_')).length} 个`);
            Logger.info(`[FuzzTestGenerator]    - 成员函数: ${functions.filter(f => !f.name.startsWith('OH_')).length} 个`);
            Logger.info(`[FuzzTestGenerator] 函数列表: ${functions.map(f => f.name).join(', ')}`);
        } else {
            Logger.warn(`[FuzzTestGenerator] ⚠️ 未找到任何可测试的函数`);
        }

        return functions;
    }
}

